#include "cmsis_os2.h"
#include "los_task.h"
#include "config_network.h"

#include "ohos_init.h"

#include "MQTTClient.h"

#include "cJSON.h"
#include "intelligent_agriculture.h"

typedef enum
{
    E_INTELLIGENT_AGRICULTURE_CMD                       = 0,
    E_INTELLIGENT_AGRICULTURE_CMD_SOIL_HUMIDITY         = 0x0001,
    E_INTELLIGENT_AGRICULTURE_CMD_LIGHT_INTENSITY       = 0x0002,
    E_INTELLIGENT_AGRICULTURE_CMD_WATER_PUMP            = 0x0003,
    E_INTELLIGENT_AGRICULTURE_CMD_SHED_COVER            = 0x0004,
    E_INTELLIGENT_AGRICULTURE_CMD_WORK_MODE             = 0x0005,
    E_INTELLIGENT_AGRICULTURE_CMD_REEST                 = 0x1234,
    E_INTELLIGENT_AGRICULTURE_CMD_MAX                   = 0xffff,
} intelligent_agriculture_cmd_type_e;

#define MQTT_DEVICES_PWD                    "nu6wce96"
//#define  IOT_CLOUD_TONGHONG   1
#ifdef IOT_CLOUD_TONGHONG
#define HOST_ADDR                           "117.78.5.125"
#else
#define HOST_ADDR                           "117.78.5.125"
#endif

#define DEVICE_ID                           "6612bcb42ccc1a5838802a53_cjRGTFXd"

#define PUBLISH_TOPIC                       "$oc/devices/"DEVICE_ID"/sys/properties/report"
#ifdef IOT_CLOUD_TONGHONG
#define SUBCRIB_TOPIC                       "$oc/devices/"DEVICE_ID"/sys/commands/+" ///request_id={request_id}"
#else
#define SUBCRIB_TOPIC                       "$oc/devices/"DEVICE_ID"/sys/commands/#" ///request_id={request_id}"
#endif

#define RESPONSE_TOPIC                      "$oc/devices/"DEVICE_ID"/sys/commands/response" ///request_id={request_id}"
#ifdef IOT_CLOUD_TONGHONG
#define CLIENT_ID                           "6612bcb42ccc1a5838802a53_cjRGTFXd_0_0_2024040715"
#define USERNAME                            "6612bcb42ccc1a5838802a53_cjRGTFXd"
#define PASSWORD                            "0b1412fa9dfba52a9e6b42d10ec5ce4d927f513ce4303af967b60c049bd377ad"
#else
#define CLIENT_ID                           "6612bcb42ccc1a5838802a53_cjRGTFXd_0_0_2024040715"
#define USERNAME                            "6612bcb42ccc1a5838802a53_cjRGTFXd"
#define PASSWORD                            "0b1412fa9dfba52a9e6b42d10ec5ce4d927f513ce4303af967b60c049bd377ad"
#endif



#define MAX_BUFFER_LENGTH                   512
#define MAX_STRING_LENGTH                   64

static unsigned char sendBuf[MAX_BUFFER_LENGTH];
static unsigned char readBuf[MAX_BUFFER_LENGTH];

Network network;
MQTTClient client;

static unsigned int mqttConnectFlag = 0;

void send_msg_to_mqtt()
{
    int rc;
    MQTTMessage message;
    char *publishtopic = PUBLISH_TOPIC;
    char payload[MAX_BUFFER_LENGTH] = {0};
    char str[MAX_STRING_LENGTH] = {0};
    
    if (mqttConnectFlag == 0)
    {
        printf("mqtt not connect\n");
        return;
    }
    
    cJSON *root = cJSON_CreateObject();
    if (root != NULL)
    {
        cJSON *serv_arr = cJSON_AddArrayToObject(root, "services");
        cJSON *arr_item = cJSON_CreateObject();
        cJSON_AddStringToObject(arr_item, "service_id", "智慧农业");
        cJSON *pro_obj = cJSON_CreateObject();
        cJSON_AddItemToObject(arr_item, "properties", pro_obj);
        
        memset(str, 0, MAX_BUFFER_LENGTH);
        sprintf(str, "%0.2f%%", g_ia_dev.soil_humidity->value);
        cJSON_AddStringToObject(pro_obj, "土壤湿度", str);
        
        memset(str, 0, MAX_BUFFER_LENGTH);
        sprintf(str, "%0.3flux", g_ia_dev.light_intensity->value);
        cJSON_AddStringToObject(pro_obj, "光线强度", str);
        
        cJSON_AddStringToObject(pro_obj, "水泵状态", (g_ia_dev.water_pump->onoff == ON) ? "运行中" : "停止");
        cJSON_AddStringToObject(pro_obj, "棚罩状态", (g_ia_dev.shed_cover->onoff == ON) ? "打开" : "关闭");
        cJSON_AddStringToObject(pro_obj, "工作模式", (g_ia_example.work_mode == WORK_MODE_AUTO) ? "无人值守" : "有人值守");
        
        cJSON_AddItemToArray(serv_arr, arr_item);
        
        char *palyload_str = cJSON_PrintUnformatted(root);
        strcpy(payload, palyload_str);
        
        cJSON_free(palyload_str);
        cJSON_Delete(root);
    }
    
    message.qos = 0;
    message.retained = 0;
    message.payload = payload;
    message.payloadlen = strlen(payload);
    
    if ((rc = MQTTPublish(&client, publishtopic, &message)) != 0)
    {
        printf("Return code from MQTT publish is %d\n", rc);
        mqttConnectFlag = 0;
    }
    else
    {
        printf("mqtt publish success:%s\n", payload);
    }
}

void process_command(intelligent_agriculture_cmd_type_e cmd_type, uint8_t value)
{
    if (cmd_type == E_INTELLIGENT_AGRICULTURE_CMD_WATER_PUMP)
    {
        if (g_ia_example.work_mode == WORK_MODE_MANUAL)
        {
            if (value == ON)
            {
                if (g_ia_dev.water_pump->onoff == OFF)
                {
                    ia_set_water_pump(g_ia_dev.water_pump, ON);
                }
                printf("工作模式：有人值守 water pump:ON\r\n");
            }
            else
            {
                if (g_ia_dev.water_pump->onoff == ON)
                {
                    ia_set_water_pump(g_ia_dev.water_pump, OFF);
                }
                printf("工作模式：有人值守 water pump:OFF\r\n");
            }
        }
    }
    else if (cmd_type == E_INTELLIGENT_AGRICULTURE_CMD_SHED_COVER)
    {
        if (g_ia_example.work_mode == WORK_MODE_MANUAL)
        {
            if (value == ON)
            {
                if (g_ia_dev.shed_cover->onoff == OFF)
                {
                    ia_set_shed_cover(g_ia_dev.shed_cover, ON);
                }
                printf("工作模式：有人值守 shed cover:ON\r\n");
            }
            else
            {
                if (g_ia_dev.shed_cover->onoff == ON)
                {
                    ia_set_shed_cover(g_ia_dev.shed_cover, OFF);
                }
                printf("工作模式：有人值守 shed cover:OFF\r\n");
            }
        }
    }
    else if (cmd_type == E_INTELLIGENT_AGRICULTURE_CMD_WORK_MODE)
    {
        if (value == WORK_MODE_AUTO)
        {
            g_ia_example.work_mode = WORK_MODE_AUTO;
            printf("工作模式：无人值守\n");
        }
        else
        {
            g_ia_example.work_mode = WORK_MODE_MANUAL;
            printf("工作模式：有人值守\n");
        }
    }
}

void mqtt_message_arrived(MessageData* data)
{
    int rc;
    cJSON *root = NULL;
    cJSON *cmd_name = NULL;
    char *cmd_name_str = NULL;
    cJSON *para_obj = NULL;
    cJSON *status_obj = NULL;
    char *value = NULL;
    char *request_id_idx = NULL;
    char request_id[20] = {0};
    MQTTMessage message;
    char payload[MAX_BUFFER_LENGTH];
    char rsptopic[128] = {0};
    
    printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len, data->topicName->lenstring.data,
           data->message->payloadlen, data->message->payload);
           
    //get request id
    request_id_idx = strstr(data->topicName->lenstring.data, "request_id=");
    strncpy(request_id, request_id_idx + 11, 19);
    //printf("request_id = %s\n", request_id);
    
    //create response topic
    sprintf(rsptopic, "%s/request_id=%s", RESPONSE_TOPIC, request_id);
    //printf("rsptopic = %s\n", rsptopic);
    
    //response message
    message.qos = 0;
    message.retained = 0;
    message.payload = payload;
    sprintf(payload, "{ \
    \"result_code\": 0, \
    \"response_name\": \"COMMAND_RESPONSE\", \
    \"paras\": { \
        \"result\": \"success\" \
    } \
    }" );
    message.payloadlen = strlen(payload);
    
    //publish the msg to responese topic
    if ((rc = MQTTPublish(&client, rsptopic, &message)) != 0)
    {
        printf("Return code from MQTT publish is %d\n", rc);
        mqttConnectFlag = 0;
    }
    
    /*{"command_name":"cmd","paras":{"cmd_value":"1"},"service_id":"server"}*/
    root = cJSON_ParseWithLength(data->message->payload, data->message->payloadlen);
    if (root != NULL)
    {
        cmd_name = cJSON_GetObjectItem(root, "command_name");
        if (cmd_name != NULL)
        {
            cmd_name_str = cJSON_GetStringValue(cmd_name);
            if (strcmp(cmd_name_str, "水泵开关") == 0)
            {
                para_obj = cJSON_GetObjectItem(root, "paras");
                status_obj = cJSON_GetObjectItem(para_obj, "水泵");
                if (status_obj != NULL)
                {
                    value = cJSON_GetStringValue(status_obj);
                    if (strcmp(value, "开") == 0)
                    {
                        process_command(E_INTELLIGENT_AGRICULTURE_CMD_WATER_PUMP, ON);
                    }
                    else
                    {
                        process_command(E_INTELLIGENT_AGRICULTURE_CMD_WATER_PUMP, OFF);
                    }
                }
            }
            else if (strcmp(cmd_name_str, "棚罩开关") == 0)
            {
                para_obj = cJSON_GetObjectItem(root, "paras");
                status_obj = cJSON_GetObjectItem(para_obj, "棚罩");
                if (status_obj != NULL)
                {
                    value = cJSON_GetStringValue(status_obj);
                    if (strcmp(value, "开") == 0)
                    {
                        process_command(E_INTELLIGENT_AGRICULTURE_CMD_SHED_COVER, ON);
                    }
                    else
                    {
                        process_command(E_INTELLIGENT_AGRICULTURE_CMD_SHED_COVER, OFF);
                    }
                }
            }
            else if (strcmp(cmd_name_str, "工作模式") == 0)
            {
                para_obj = cJSON_GetObjectItem(root, "paras");
                status_obj = cJSON_GetObjectItem(para_obj, "模式");
                if (status_obj != NULL)
                {
                    value = cJSON_GetStringValue(status_obj);
                    if (strcmp(value, "无人值守") == 0)
                    {
                        process_command(E_INTELLIGENT_AGRICULTURE_CMD_WORK_MODE, WORK_MODE_AUTO);
                    }
                    else
                    {
                        process_command(E_INTELLIGENT_AGRICULTURE_CMD_WORK_MODE, WORK_MODE_MANUAL);
                    }
                }
            }
        }
    }
    
    cJSON_Delete(root);
}

int wait_message()
{
    MQTTYield(&client, 5000);
    if (mqttConnectFlag == 0)
    {
        return 0;
    }
    return 1;
}

int mqtt_connected()
{
    if (mqttConnectFlag == 0)
    {
        return 0;
    }
    return 1;
}

void mqtt_init()
{
    int rc;
    
    printf("Starting MQTT...\n");
    /*网络初始化*/
    NetworkInit(&network);
    
begin:
    /* 连接网络*/
    printf("NetworkConnect  ...\n");
    NetworkConnect(&network, HOST_ADDR, 1883);
    printf("MQTTClientInit  ...\n");
    /*MQTT客户端初始化*/
    MQTTClientInit(&client, &network, 2000, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));
    
    MQTTString clientId = MQTTString_initializer;
    clientId.cstring = CLIENT_ID;//DEVICE_ID;
    
    MQTTString userName = MQTTString_initializer;
    userName.cstring = USERNAME;//DEVICE_ID;
    
    MQTTString password = MQTTString_initializer;
    password.cstring = PASSWORD;//MQTT_DEVICES_PWD;
    
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.clientID = clientId;
    data.username = userName;
    data.password = password;
    data.willFlag = 0;
    data.MQTTVersion = 4;
    data.keepAliveInterval = 60;
    data.cleansession = 1;
    
    printf("MQTTConnect  ...\n");
    rc = MQTTConnect(&client, &data);
    if (rc != 0)
    {
        printf("MQTTConnect: %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        osDelay(200);
        goto begin;
    }
    
    printf("MQTTSubscribe  ...\n");
    rc = MQTTSubscribe(&client, SUBCRIB_TOPIC, 0, mqtt_message_arrived);
    if (rc != 0)
    {
        printf("MQTTSubscribe: %d\n", rc);
        osDelay(200);
        goto begin;
    }
    
    mqttConnectFlag = 1;
}

